package com.edouardbataille.open.handler
{
	import __AS3__.vec.Vector;
	
	import com.adobe.crypto.SHA1;
	import com.edouardbataille.open.MySqlSocket;
	import com.edouardbataille.open.MysqlConst;
	import com.edouardbataille.open.bytes.ByteReader;
	import com.edouardbataille.open.sender.Sender;
	
	import flash.utils.ByteArray;

	public class InitHandler extends Sender implements IHandler
	{
		private var login : String;
		
		private var pass : String;

		private var catalog : String;
		
		private var scrumble : String;
		
		private var server_language : uint;

		public function InitHandler (con : MySqlSocket, login : String, pass : String, catalog : String)
		{
			super (con);
			this.login = login;
			this.pass = pass;
			this.catalog = catalog;
		}

		public function handleData (packets:Vector.<ByteReader>, con : MySqlSocket) : void
		{
			this.con = con;
			
			var data : ByteReader = packets[0];
			var length : uint = data.readPacketLength();
			var packet : uint = data.readPacketNum();
			if (packet == 2)
			{
				if (length == 7 && data.readByte() == 0)
					con.isConnect(true);
				else
					con.isConnect(false);
				return;
			}
			var protocol : uint = data.readByte();
			var serverVersion : String = "";
			var serverVersionLength : int = length - 45;
			while (data.bytesAvailable && serverVersionLength > 0)
			{
				var byte : uint = data.readByte();
				serverVersion += String.fromCharCode(byte);
				--serverVersionLength;
			}
			var thread_id : uint = 0;

			thread_id = data.readInt();
			scrumble = data.readString("latin1");
			var server_capabilities : uint = data.readByte() << 16 + data.readByte();
			server_language = data.readByte();
			var server_status : uint = data.readByte() << 16 + data.readByte();
			var i : int;
			for (i = 0; i < 13 && data.bytesAvailable; ++i)
			{
				data.readByte();
			}
			scrumble += data.readString("latin1");
			doLogin();
		}
		
		private function doLogin () : void
		{
			var response : ByteArray = new ByteArray();

			var flag : uint = 0;
			flag |= MysqlConst.CLIENT_SECURE_CONNECTION;
			flag |= MysqlConst.CLIENT_PROTOCOL_41;
			flag |= MysqlConst.CLIENT_LONG_PASSWORD;
			flag |= MysqlConst.CLIENT_CONNECT_WITH_DB;

			// flag
			response.writeByte(flag & 0xFF);
			response.writeByte(flag >>> 8);
			response.writeByte(flag >>> 16);
			response.writeByte(flag >>> 24);

			// packet
			var maxPacket : int = 256 * 256 * 256 - 1;
			response.writeInt(maxPacket);

			// charset (8)
			response.writeByte(server_language);

			// null byte
			for (var i : int = 0; i < 23; ++i)
			{
				response.writeByte(0x00);
			}

			//username
			response.writeMultiByte(login, "latin1");
			response.writeByte(0x00);

			response.writeByte(0x14);
			var pass : ByteArray = getToken(pass);
			response.writeBytes(pass);
			if (catalog)
				response.writeUTFBytes(catalog);
			response.writeByte(0x00);
			
			send(response, 1);
		}

		private function getToken (pass : String) : ByteArray
		{
			return scramble411(pass, scrumble);
		}

		public static function scramble411 (password : String, seed : String) : ByteArray
		{
			var phs1 : ByteArray = SHA1.hashToByteArray(password);
			var phs2 : ByteArray = SHA1.hashBytesToByteArray(phs1);
			var phs3 : ByteArray = new ByteArray();
			for (var i : int = 0; i < seed.length; i++)
			{
				phs3.writeByte(seed.charCodeAt(i) & 0xFF);
			}
			phs3.writeBytes(phs2);
			phs3.position = 0;

			var toBeXored : ByteArray = SHA1.hashBytesToByteArray(phs3);
			toBeXored.position = 0;

			var xored : ByteArray = new ByteArray();

			for (var n : int = 0; n < toBeXored.length; n++)
			{
				var b1 : int = toBeXored.readByte();
				var b2 : int = phs1.readByte();
				xored.writeByte(b1 ^ b2);
			}

			xored.position = 0;

			return xored;
		}
	}
}